/*
 * Copyright (C) 2015 grandcentrix GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.grandcentrix.tray.provider;

import net.grandcentrix.tray.core.TrayLog;
import net.grandcentrix.tray.core.TrayRuntimeException;
import net.grandcentrix.tray.ResourceTable;

import net.grandcentrix.tray.util.LogUtil;
import ohos.aafwk.content.Intent;
import ohos.app.Context;
import ohos.bundle.AbilityInfo;
import ohos.rpc.RemoteException;
import ohos.sysappcomponents.calendar.column.BaseColumns;
import ohos.utils.net.Uri;
import ohos.os.ProcessManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.VisibleForTesting;

import java.util.List;

/**
 * Contract defining the data in the {@link TrayContentProvider}. Use {@link TrayProviderHelper} to
 * access them.
 * <p>
 * Created by jannisveerkamp on 17.09.14.
 */
public class TrayContract {
    private static final String TAG = TrayContract.class.getSimpleName();

    /**
     * default preferences
     */
    public interface Preferences {

        interface Columns extends BaseColumns {

            String ID = BaseColumns.ID;

            String KEY = TrayDBHelper.KEY;

            String VALUE = TrayDBHelper.VALUE;

            String MODULE = TrayDBHelper.MODULE;

            String CREATED = TrayDBHelper.CREATED; // DATE

            String UPDATED = TrayDBHelper.UPDATED; // DATE

            String MIGRATED_KEY = TrayDBHelper.MIGRATED_KEY;
        }

        String BASE_PATH = "preferences";
    }

    /**
     * trays internal preferences to hold things like the version number
     */
    public interface InternalPreferences extends Preferences {

        String BASE_PATH = "internal_preferences";
    }

    @VisibleForTesting
    static String sAuthority = "legacyTrayAuthority";

    @NonNls
    public static Uri generateContentUri(@NonNls final Context context) {
        return generateContentUri(context, Preferences.BASE_PATH);
    }

    @NonNls
    /*package*/ static Uri generateInternalContentUri(@NonNls final Context context) {
        return generateContentUri(context, InternalPreferences.BASE_PATH);
    }

    /**
     * Inform if someone use the old way to set or override the authority
     *
     * @param context
     */
    private static void checkOldWayToSetAuthority(@NonNls final Context context) {
        if (!"legacyTrayAuthority".equals(context.getString(ResourceTable.String_legacy))) {
            LogUtil.error(TAG, "Deprecated way of defining the Tray authority detected\n"
                    + "#########################################\n"
                    + "#########################################\n"
                    + "#########################################\n"
                    + "Don't set the authority with `tray__authority` in your build.gradle.\n"
                    + "#########################################\n"
                    + "#########################################\n"
                    + "#########################################\n");
        }
    }

    @NonNls
    private static Uri generateContentUri(@NonNls final Context context, final String basepath) {

        final String authority = getAuthority(context);
        final Uri authorityUri = Uri.parse("content://" + authority);
        //noinspection UnnecessaryLocalVariable
        final Uri contentUri = Uri.appendEncodedPathToUri(authorityUri, basepath);

        return contentUri;
    }

    @NonNls
    private static synchronized String getAuthority(@NonNls final Context context) {
        if (sAuthority != null) {
            return sAuthority;
        }

        checkOldWayToSetAuthority(context);

        // read all providers of the app and find the TrayContentProvider to read the authority
        Intent intent = new Intent();
        intent.setElement(context.getElementName());

        try {
            final List<AbilityInfo> providers = context.getBundleManager().queryAbilityByIntent(intent, ProcessManager.getUid(), 0);
            if (providers != null) {
                for (AbilityInfo provider : providers) {
                    if (provider.className.equals(TrayContentProvider.class.getName())) {
                        sAuthority = provider.getReadPermission();
                        TrayLog.v("found authority: " + sAuthority);
                        return sAuthority;
                    }
                }
            }
        } catch(RemoteException e) {
            e.getMessage();
        }

        // Should never happen. Otherwise we implemented tray in a wrong way!
        throw new TrayRuntimeException("Internal tray error. "
                + "Could not find the provider authority. "
                + "Please fill an issue to Harmony Tray team.");
    }
}
